home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / distutils / fancy_getopt.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  12KB  |  382 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.4)
  3.  
  4. '''distutils.fancy_getopt
  5.  
  6. Wrapper around the standard getopt module that provides the following
  7. additional features:
  8.   * short and long options are tied together
  9.   * options have help strings, so fancy_getopt could potentially
  10.     create a complete usage summary
  11.   * options set attributes of a passed-in object
  12. '''
  13. __revision__ = '$Id: fancy_getopt.py,v 1.30 2004/11/10 22:23:14 loewis Exp $'
  14. import sys
  15. import string
  16. import re
  17. from types import *
  18. import getopt
  19. from distutils.errors import *
  20. longopt_pat = '[a-zA-Z](?:[a-zA-Z0-9-]*)'
  21. longopt_re = re.compile('^%s$' % longopt_pat)
  22. neg_alias_re = re.compile('^(%s)=!(%s)$' % (longopt_pat, longopt_pat))
  23. longopt_xlate = string.maketrans('-', '_')
  24.  
  25. class FancyGetopt:
  26.     '''Wrapper around the standard \'getopt()\' module that provides some
  27.     handy extra functionality:
  28.       * short and long options are tied together
  29.       * options have help strings, and help text can be assembled
  30.         from them
  31.       * options set attributes of a passed-in object
  32.       * boolean options can have "negative aliases" -- eg. if
  33.         --quiet is the "negative alias" of --verbose, then "--quiet"
  34.         on the command line sets \'verbose\' to false
  35.     '''
  36.     
  37.     def __init__(self, option_table = None):
  38.         self.option_table = option_table
  39.         self.option_index = { }
  40.         if self.option_table:
  41.             self._build_index()
  42.         
  43.         self.alias = { }
  44.         self.negative_alias = { }
  45.         self.short_opts = []
  46.         self.long_opts = []
  47.         self.short2long = { }
  48.         self.attr_name = { }
  49.         self.takes_arg = { }
  50.         self.option_order = []
  51.  
  52.     
  53.     def _build_index(self):
  54.         self.option_index.clear()
  55.         for option in self.option_table:
  56.             self.option_index[option[0]] = option
  57.         
  58.  
  59.     
  60.     def set_option_table(self, option_table):
  61.         self.option_table = option_table
  62.         self._build_index()
  63.  
  64.     
  65.     def add_option(self, long_option, short_option = None, help_string = None):
  66.         if self.option_index.has_key(long_option):
  67.             raise DistutilsGetoptError, "option conflict: already an option '%s'" % long_option
  68.         else:
  69.             option = (long_option, short_option, help_string)
  70.             self.option_table.append(option)
  71.             self.option_index[long_option] = option
  72.  
  73.     
  74.     def has_option(self, long_option):
  75.         """Return true if the option table for this parser has an
  76.         option with long name 'long_option'."""
  77.         return self.option_index.has_key(long_option)
  78.  
  79.     
  80.     def get_attr_name(self, long_option):
  81.         """Translate long option name 'long_option' to the form it
  82.         has as an attribute of some object: ie., translate hyphens
  83.         to underscores."""
  84.         return string.translate(long_option, longopt_xlate)
  85.  
  86.     
  87.     def _check_alias_dict(self, aliases, what):
  88.         for alias, opt in aliases.items():
  89.             if not self.option_index.has_key(alias):
  90.                 raise DistutilsGetoptError, "invalid %s '%s': option '%s' not defined" % (what, alias, alias)
  91.             
  92.             if not self.option_index.has_key(opt):
  93.                 raise DistutilsGetoptError, "invalid %s '%s': aliased option '%s' not defined" % (what, alias, opt)
  94.                 continue
  95.         
  96.  
  97.     
  98.     def set_aliases(self, alias):
  99.         '''Set the aliases for this option parser.'''
  100.         self._check_alias_dict(alias, 'alias')
  101.         self.alias = alias
  102.  
  103.     
  104.     def set_negative_aliases(self, negative_alias):
  105.         """Set the negative aliases for this option parser.
  106.         'negative_alias' should be a dictionary mapping option names to
  107.         option names, both the key and value must already be defined
  108.         in the option table."""
  109.         self._check_alias_dict(negative_alias, 'negative alias')
  110.         self.negative_alias = negative_alias
  111.  
  112.     
  113.     def _grok_option_table(self):
  114.         """Populate the various data structures that keep tabs on the
  115.         option table.  Called by 'getopt()' before it can do anything
  116.         worthwhile.
  117.         """
  118.         self.long_opts = []
  119.         self.short_opts = []
  120.         self.short2long.clear()
  121.         self.repeat = { }
  122.         for option in self.option_table:
  123.             if len(option) == 3:
  124.                 (long, short, help) = option
  125.                 repeat = 0
  126.             elif len(option) == 4:
  127.                 (long, short, help, repeat) = option
  128.             else:
  129.                 raise ValueError, 'invalid option tuple: %r' % (option,)
  130.             if type(long) is not StringType or len(long) < 2:
  131.                 raise DistutilsGetoptError, "invalid long option '%s': must be a string of length >= 2" % long
  132.             
  133.             if not short is None and type(short) is StringType and len(short) == 1:
  134.                 raise DistutilsGetoptError, "invalid short option '%s': must a single character or None" % short
  135.             
  136.             self.repeat[long] = repeat
  137.             self.long_opts.append(long)
  138.             if long[-1] == '=':
  139.                 if short:
  140.                     short = short + ':'
  141.                 
  142.                 long = long[0:-1]
  143.                 self.takes_arg[long] = 1
  144.             else:
  145.                 alias_to = self.negative_alias.get(long)
  146.                 if alias_to is not None:
  147.                     if self.takes_arg[alias_to]:
  148.                         raise DistutilsGetoptError, "invalid negative alias '%s': aliased option '%s' takes a value" % (long, alias_to)
  149.                     
  150.                     self.long_opts[-1] = long
  151.                     self.takes_arg[long] = 0
  152.                 else:
  153.                     self.takes_arg[long] = 0
  154.             alias_to = self.alias.get(long)
  155.             if alias_to is not None:
  156.                 if self.takes_arg[long] != self.takes_arg[alias_to]:
  157.                     raise DistutilsGetoptError, "invalid alias '%s': inconsistent with aliased option '%s' (one of them takes a value, the other doesn't" % (long, alias_to)
  158.                 
  159.             
  160.             if not longopt_re.match(long):
  161.                 raise DistutilsGetoptError, ("invalid long option name '%s' " + '(must be letters, numbers, hyphens only') % long
  162.             
  163.             self.attr_name[long] = self.get_attr_name(long)
  164.             if short:
  165.                 self.short_opts.append(short)
  166.                 self.short2long[short[0]] = long
  167.                 continue
  168.         
  169.  
  170.     
  171.     def getopt(self, args = None, object = None):
  172.         """Parse command-line options in args. Store as attributes on object.
  173.  
  174.         If 'args' is None or not supplied, uses 'sys.argv[1:]'.  If
  175.         'object' is None or not supplied, creates a new OptionDummy
  176.         object, stores option values there, and returns a tuple (args,
  177.         object).  If 'object' is supplied, it is modified in place and
  178.         'getopt()' just returns 'args'; in both cases, the returned
  179.         'args' is a modified copy of the passed-in 'args' list, which
  180.         is left untouched.
  181.         """
  182.         if args is None:
  183.             args = sys.argv[1:]
  184.         
  185.         if object is None:
  186.             object = OptionDummy()
  187.             created_object = 1
  188.         else:
  189.             created_object = 0
  190.         self._grok_option_table()
  191.         short_opts = string.join(self.short_opts)
  192.         
  193.         try:
  194.             (opts, args) = getopt.getopt(args, short_opts, self.long_opts)
  195.         except getopt.error:
  196.             msg = None
  197.             raise DistutilsArgError, msg
  198.  
  199.         for opt, val in opts:
  200.             if len(opt) == 2 and opt[0] == '-':
  201.                 opt = self.short2long[opt[1]]
  202.             else:
  203.                 opt = opt[2:]
  204.             alias = self.alias.get(opt)
  205.             if alias:
  206.                 opt = alias
  207.             
  208.             if not self.takes_arg[opt]:
  209.                 alias = self.negative_alias.get(opt)
  210.                 if alias:
  211.                     opt = alias
  212.                     val = 0
  213.                 else:
  214.                     val = 1
  215.             
  216.             attr = self.attr_name[opt]
  217.             if val and self.repeat.get(attr) is not None:
  218.                 val = getattr(object, attr, 0) + 1
  219.             
  220.             setattr(object, attr, val)
  221.             self.option_order.append((opt, val))
  222.         
  223.         if created_object:
  224.             return (args, object)
  225.         else:
  226.             return args
  227.  
  228.     
  229.     def get_option_order(self):
  230.         """Returns the list of (option, value) tuples processed by the
  231.         previous run of 'getopt()'.  Raises RuntimeError if
  232.         'getopt()' hasn't been called yet.
  233.         """
  234.         if self.option_order is None:
  235.             raise RuntimeError, "'getopt()' hasn't been called yet"
  236.         else:
  237.             return self.option_order
  238.  
  239.     
  240.     def generate_help(self, header = None):
  241.         '''Generate help text (a list of strings, one per suggested line of
  242.         output) from the option table for this FancyGetopt object.
  243.         '''
  244.         max_opt = 0
  245.         for option in self.option_table:
  246.             long = option[0]
  247.             short = option[1]
  248.             l = len(long)
  249.             if long[-1] == '=':
  250.                 l = l - 1
  251.             
  252.             if short is not None:
  253.                 l = l + 5
  254.             
  255.             if l > max_opt:
  256.                 max_opt = l
  257.                 continue
  258.         
  259.         opt_width = max_opt + 2 + 2 + 2
  260.         line_width = 78
  261.         text_width = line_width - opt_width
  262.         big_indent = ' ' * opt_width
  263.         if header:
  264.             lines = [
  265.                 header]
  266.         else:
  267.             lines = [
  268.                 'Option summary:']
  269.         for option in self.option_table:
  270.             (long, short, help) = option[:3]
  271.             text = wrap_text(help, text_width)
  272.             if long[-1] == '=':
  273.                 long = long[0:-1]
  274.             
  275.             if short is None:
  276.                 if text:
  277.                     lines.append('  --%-*s  %s' % (max_opt, long, text[0]))
  278.                 else:
  279.                     lines.append('  --%-*s  ' % (max_opt, long))
  280.             else:
  281.                 opt_names = '%s (-%s)' % (long, short)
  282.                 if text:
  283.                     lines.append('  --%-*s  %s' % (max_opt, opt_names, text[0]))
  284.                 else:
  285.                     lines.append('  --%-*s' % opt_names)
  286.             for l in text[1:]:
  287.                 lines.append(big_indent + l)
  288.             
  289.         
  290.         return lines
  291.  
  292.     
  293.     def print_help(self, header = None, file = None):
  294.         if file is None:
  295.             file = sys.stdout
  296.         
  297.         for line in self.generate_help(header):
  298.             file.write(line + '\n')
  299.         
  300.  
  301.  
  302.  
  303. def fancy_getopt(options, negative_opt, object, args):
  304.     parser = FancyGetopt(options)
  305.     parser.set_negative_aliases(negative_opt)
  306.     return parser.getopt(args, object)
  307.  
  308. WS_TRANS = string.maketrans(string.whitespace, ' ' * len(string.whitespace))
  309.  
  310. def wrap_text(text, width):
  311.     """wrap_text(text : string, width : int) -> [string]
  312.  
  313.     Split 'text' into multiple lines of no more than 'width' characters
  314.     each, and return the list of strings that results.
  315.     """
  316.     if text is None:
  317.         return []
  318.     
  319.     if len(text) <= width:
  320.         return [
  321.             text]
  322.     
  323.     text = string.expandtabs(text)
  324.     text = string.translate(text, WS_TRANS)
  325.     chunks = re.split('( +|-+)', text)
  326.     chunks = filter(None, chunks)
  327.     lines = []
  328.     while chunks:
  329.         cur_line = []
  330.         cur_len = 0
  331.         while chunks:
  332.             l = len(chunks[0])
  333.             if cur_len + l <= width:
  334.                 cur_line.append(chunks[0])
  335.                 del chunks[0]
  336.                 cur_len = cur_len + l
  337.                 continue
  338.             if cur_line and cur_line[-1][0] == ' ':
  339.                 del cur_line[-1]
  340.             
  341.             break
  342.         if chunks:
  343.             if cur_len == 0:
  344.                 cur_line.append(chunks[0][0:width])
  345.                 chunks[0] = chunks[0][width:]
  346.             
  347.             if chunks[0][0] == ' ':
  348.                 del chunks[0]
  349.             
  350.         
  351.         lines.append(string.join(cur_line, ''))
  352.     return lines
  353.  
  354.  
  355. def translate_longopt(opt):
  356.     '''Convert a long option name to a valid Python identifier by
  357.     changing "-" to "_".
  358.     '''
  359.     return string.translate(opt, longopt_xlate)
  360.  
  361.  
  362. class OptionDummy:
  363.     '''Dummy class just used as a place to hold command-line option
  364.     values as instance attributes.'''
  365.     
  366.     def __init__(self, options = []):
  367.         """Create a new OptionDummy instance.  The attributes listed in
  368.         'options' will be initialized to None."""
  369.         for opt in options:
  370.             setattr(self, opt, None)
  371.         
  372.  
  373.  
  374. if __name__ == '__main__':
  375.     text = 'Tra-la-la, supercalifragilisticexpialidocious.\nHow *do* you spell that odd word, anyways?\n(Someone ask Mary -- she\'ll know [or she\'ll\nsay, "How should I know?"].)'
  376.     for w in (10, 20, 30, 40):
  377.         print 'width: %d' % w
  378.         print string.join(wrap_text(text, w), '\n')
  379.         print 
  380.     
  381.  
  382.